use std::{
	fmt::Write,
	net::SocketAddr,
	sync::atomic::{AtomicU64, Ordering},
};

use crate::sip2::utils::{generate_disorder_u8s, trim_and_skip};
use bytes::{Bytes, BytesMut};
use tools::utils::gen_id::get_now_duration;
use tracing::error;

use super::{
	utils::{generate_full_sip_url, get_bytes_str, WriteSip},
	SipMethod, BRANCH_CHAR, SEPARATOR, SIP_VERSION_SUFFIX,
};

///sip的头字段名.
#[derive(Debug, Eq, Hash, Clone)]
pub(crate) enum SipHeadField {
	CallID(Bytes),
	From(Bytes),
	To(Bytes),
	Via(Bytes),
	Route(Bytes),
	RecordRoute(Bytes),
	Contact(Bytes),
	MaxForwards(Bytes),
	ContentLength(Bytes),
	ContentType(Bytes),
	Supported(Bytes),
	Allow(Bytes),
	AllowEvents(Bytes),
	Expires(Bytes),
	CSeq(Bytes),
	SessionExpires(Bytes),
	MinSE(Bytes),
	PAssertedIdentity(Bytes),
	PEarlyMedia(Bytes),
	RemotePartyID(Bytes),
	UserAgent(Bytes),
	WWWAuthenticate(Bytes),
	Authorization(Bytes),
	Require(Bytes),
	Reason(Bytes),
	RetryAfter(Bytes),
	Unknown,
}

impl Default for SipHeadField {
	fn default() -> Self {
		SipHeadField::Unknown
	}
}

impl PartialEq for SipHeadField {
	fn eq(&self, other: &Self) -> bool {
		match (self, other) {
			(Self::CallID(_), Self::CallID(_)) => true,
			(Self::From(_), Self::From(_)) => true,
			(Self::To(_), Self::To(_)) => true,
			(Self::Via(_), Self::Via(_)) => true,
			(Self::Route(_), Self::Route(_)) => true,
			(Self::RecordRoute(_), Self::RecordRoute(_)) => true,
			(Self::Contact(_), Self::Contact(_)) => true,
			(Self::MaxForwards(_), Self::MaxForwards(_)) => true,
			(Self::ContentLength(_), Self::ContentLength(_)) => true,
			(Self::ContentType(_), Self::ContentType(_)) => true,
			(Self::Supported(_), Self::Supported(_)) => true,
			(Self::Allow(_), Self::Allow(_)) => true,
			(Self::AllowEvents(_), Self::AllowEvents(_)) => true,
			(Self::Expires(_), Self::Expires(_)) => true,
			(Self::CSeq(_), Self::CSeq(_)) => true,
			(Self::SessionExpires(_), Self::SessionExpires(_)) => true,
			(Self::MinSE(_), Self::MinSE(_)) => true,
			(Self::PAssertedIdentity(_), Self::PAssertedIdentity(_)) => true,
			(Self::PEarlyMedia(_), Self::PEarlyMedia(_)) => true,
			(Self::RemotePartyID(_), Self::RemotePartyID(_)) => true,
			(Self::UserAgent(_), Self::UserAgent(_)) => true,
			(Self::WWWAuthenticate(_), Self::WWWAuthenticate(_)) => true,
			(Self::Authorization(_), Self::Authorization(_)) => true,
			(Self::Require(_), Self::Require(_)) => true,
			(Self::Reason(_), Self::Reason(_)) => true,
			(Self::RetryAfter(_), Self::RetryAfter(_)) => true,
			_ => false,
		}
	}
}

impl SipHeadField {
	pub(crate) fn as_str(&self) -> &str {
		&get_bytes_str(self.bytes())
	}

	pub fn bytes(&self) -> &Bytes {
		match self {
			Self::CallID(ref b) => b,
			Self::From(b) => &b,
			Self::To(b) => &b,
			Self::Via(b) => &b,
			Self::Route(b) => &b,
			Self::RecordRoute(b) => &b,
			Self::Contact(b) => &b,
			Self::MaxForwards(b) => &b,
			Self::ContentLength(b) => &b,
			Self::ContentType(b) => &b,
			Self::Supported(b) => &b,
			Self::Allow(b) => &b,
			Self::AllowEvents(b) => &b,
			Self::Expires(b) => &b,
			Self::CSeq(b) => &b,
			Self::SessionExpires(b) => &b,
			Self::MinSE(b) => &b,
			Self::PAssertedIdentity(b) => &b,
			Self::PEarlyMedia(b) => &b,
			Self::RemotePartyID(b) => &b,
			Self::UserAgent(b) => &b,
			Self::WWWAuthenticate(b) => &b,
			Self::Authorization(b) => &b,
			Self::Require(b) => &b,
			Self::Reason(b) => &b,
			Self::RetryAfter(b) => &b,
			Self::Unknown => &EMPTY_BYTES,
		}
	}

	#[inline]
	pub fn write<W>(&self, w: &mut W)
	where
		W: WriteSip,
	{
		match self {
			Self::CallID(b) => w.put_head_field(CALL_ID, &b),
			Self::From(b) => w.put_head_field(FROM, &b),
			Self::To(b) => w.put_head_field(TO, &b),
			Self::Via(b) => w.put_head_field(VIA, &b),
			Self::Route(b) => w.put_head_field(ROUTE, &b),
			Self::RecordRoute(b) => w.put_head_field(RECORD_ROUTE, &b),
			Self::Contact(b) => w.put_head_field(CONTACT, &b),
			Self::MaxForwards(b) => w.put_head_field(MAX_FORWARDS, &b),
			Self::ContentLength(b) => w.put_head_field(CONTENT_LENGTH, &b),
			Self::ContentType(b) => w.put_head_field(CONTENT_TYPE, &b),
			Self::Supported(b) => w.put_head_field(SUPPORTED, &b),
			Self::Allow(b) => w.put_head_field(ALLOW, &b),
			Self::AllowEvents(b) => w.put_head_field(ALLOW_EVENTS, &b),
			Self::Expires(b) => w.put_head_field(EXPIRES, &b),
			Self::CSeq(b) => w.put_head_field(CSEQ, &b),
			Self::SessionExpires(b) => w.put_head_field(SESSION_EXPIRES, &b),
			Self::MinSE(b) => w.put_head_field(MIN_SE, &b),
			Self::PAssertedIdentity(b) => w.put_head_field(P_ASSERTED_IDENTITY, &b),
			Self::PEarlyMedia(b) => w.put_head_field(P_EARLY_MEDIA, &b),
			Self::RemotePartyID(b) => w.put_head_field(REMOTE_PARTY_ID, &b),
			Self::UserAgent(b) => w.put_head_field(USER_AGENT, &b),
			Self::WWWAuthenticate(b) => w.put_head_field(WWW_AUTHENTICATE, &b),
			Self::Authorization(b) => w.put_head_field(AUTHORIZATION, &b),
			Self::Require(b) => w.put_head_field(REQUIRE, &b),
			Self::Reason(b) => w.put_head_field(REASON, &b),
			Self::RetryAfter(b) => w.put_head_field(RETRY_AFTER, &b),
			Self::Unknown => {}
		}
	}

	///给定一行的数据.将此数据转为头字段的相关数据.
	///
	/// 给的数据应该只有一行,不包括结束符
	pub fn from_bytes_line(mut b: Bytes) -> Self {
		for m in 0..b.len() {
			if b[m] == b':' {
				let f = trim_and_skip(&b.split_to(m), 0);
				//这里会带一个':'.需要跳过一下.
				let b = trim_and_skip(&b, 1);
				return match f.as_ref() {
					CALL_ID => Self::CallID(b),
					FROM => Self::From(b),
					TO => Self::To(b),
					VIA => Self::Via(b),
					ROUTE => Self::Route(b),
					RECORD_ROUTE => Self::RecordRoute(b),
					CONTACT => Self::Contact(b),
					MAX_FORWARDS => Self::MaxForwards(b),
					CONTENT_LENGTH => Self::ContentLength(b),
					CONTENT_TYPE => Self::ContentType(b),
					SUPPORTED => Self::Supported(b),
					ALLOW => Self::Allow(b),
					ALLOW_EVENTS => Self::AllowEvents(b),
					EXPIRES => Self::Expires(b),
					CSEQ => Self::CSeq(b),
					SESSION_EXPIRES => Self::SessionExpires(b),
					MIN_SE => Self::MinSE(b),
					P_ASSERTED_IDENTITY => Self::PAssertedIdentity(b),
					P_EARLY_MEDIA => Self::PEarlyMedia(b),
					REMOTE_PARTY_ID => Self::RemotePartyID(b),
					USER_AGENT => Self::UserAgent(b),
					WWW_AUTHENTICATE => Self::WWWAuthenticate(b),
					AUTHORIZATION => Self::Authorization(b),
					REQUIRE => Self::Require(b),
					REASON => Self::RetryAfter(b),
					RETRY_AFTER => Self::Reason(b),
					_ => Self::Unknown,
				};
			}
		}

		error!("得到sip头数据异常.无法解码.没有必要的内容:{b:?}");
		Self::Unknown
	}

	///生成via的方法
	#[inline]
	pub(crate) fn generate_via(tp_name: &str, ip: &SocketAddr) -> Self {
		static BRANCH_VALUE: AtomicU64 = AtomicU64::new(1223380832951995424u64);

		let mut buf = BytesMut::with_capacity(90);

		buf.extend_from_slice(SIP_VERSION_SUFFIX);
		buf.extend_from_slice(tp_name.as_bytes());
		buf.extend_from_slice(SEPARATOR);
		buf.extend_from_slice(ip.to_string().as_bytes());
		buf.extend_from_slice(BRANCH_CHAR);
		buf.extend_from_slice(&generate_disorder_u8s(
			BRANCH_VALUE.fetch_add(72907555602776961, Ordering::Relaxed),
		));

		SipHeadField::Via(buf.freeze())
	}

	///生成cseq的方法
	#[inline]
	pub(crate) fn generate_cseq(method: SipMethod) -> Self {
		let mut buf = BytesMut::with_capacity(20);

		//这里目的是将数字转换成字符串
		buf.extend_from_slice(b"1 ");
		buf.extend_from_slice(method.as_bytes());

		SipHeadField::CSeq(buf.freeze())
	}

	pub(crate) fn generate_callid() -> Self {
		let time = get_now_duration();
		// let mut buf = BytesMut::with_capacity(32);

		// buf.extend_from_slice(&generate_disorder_u128_to_u8s(time.as_millis()));
		// buf.extend_from_slice(&generate_disorder_u8s(time.as_secs()));

		SipHeadField::CallID(time.as_nanos().to_string().into())
	}

	#[inline]
	pub(crate) fn generate_from(name: &str, num: &str, ip: &SocketAddr) -> Self {
		SipHeadField::From(generate_full_sip_url(name, num, &ip.ip().to_string(), true))
	}

	///生成的to...这个用来呼叫的,to不带tag字段
	#[inline]
	pub(crate) fn generate_to(name: &str, num: &str, ip: &SocketAddr) -> Self {
		SipHeadField::To(generate_full_sip_url(
			name,
			num,
			&ip.ip().to_string(),
			false,
		))
	}

	#[inline]
	pub(crate) fn generate_p_asserted_identity(name: &str, num: &str, ip: &SocketAddr) -> Self {
		SipHeadField::PAssertedIdentity(generate_full_sip_url(
			name,
			num,
			&ip.ip().to_string(),
			false,
		))
	}

	#[inline]
	pub(crate) fn genterate_contact(caller_num: &str, ip: &SocketAddr) -> Self {
		SipHeadField::Contact(generate_full_sip_url(
			"",
			caller_num,
			&ip.to_string(),
			false,
		))
	}

	pub(crate) fn genterate_length(len: usize) -> SipHeadField {
		let mut buf = BytesMut::with_capacity(8);

		let _ = write!(&mut buf, "{}", len);
		SipHeadField::ContentLength(buf.freeze())
	}
}

pub(crate) const CALL_ID: &'static [u8] = b"Call-ID";
pub(crate) const FROM: &'static [u8] = b"From";
pub(crate) const TO: &'static [u8] = b"To";
pub(crate) const VIA: &'static [u8] = b"Via";
pub(crate) const ROUTE: &'static [u8] = b"Route";
pub(crate) const RECORD_ROUTE: &'static [u8] = b"Record-Route";
pub(crate) const CONTACT: &'static [u8] = b"Contact";
pub(crate) const MAX_FORWARDS: &'static [u8] = b"Max-Forwards";
pub(crate) const CONTENT_LENGTH: &'static [u8] = b"Content-Length";
pub(crate) const CONTENT_TYPE: &'static [u8] = b"Content-Type";
pub(crate) const SUPPORTED: &'static [u8] = b"Supported";
pub(crate) const ALLOW: &'static [u8] = b"Allow";
pub(crate) const ALLOW_EVENTS: &'static [u8] = b"Allow-Events";
pub(crate) const EXPIRES: &'static [u8] = b"Expires";
pub(crate) const CSEQ: &'static [u8] = b"CSeq";
pub(crate) const SESSION_EXPIRES: &'static [u8] = b"Session-Expires";
pub(crate) const MIN_SE: &'static [u8] = b"Min-SE";
pub(crate) const P_ASSERTED_IDENTITY: &'static [u8] = b"P-Asserted-Identity";
pub(crate) const P_EARLY_MEDIA: &'static [u8] = b"P-Early-Media";
pub(crate) const REMOTE_PARTY_ID: &'static [u8] = b"Remote-Party-ID";
pub(crate) const USER_AGENT: &'static [u8] = b"User-Agent";
pub(crate) const WWW_AUTHENTICATE: &'static [u8] = b"WWW-Authenticate";
pub(crate) const AUTHORIZATION: &'static [u8] = b"Authorization";
pub(crate) const REQUIRE: &'static [u8] = b"Require";
pub(crate) const REASON: &'static [u8] = b"Reason";
pub(crate) const RETRY_AFTER: &'static [u8] = b"Retry-After: ";

pub(crate) static EMPTY_BYTES: Bytes = Bytes::new();
